package com.cl.container;

import com.cl.annotation.ClComponent;
import com.cl.util.ScannerClass;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentHashMap;

public class MyContainer {

    /*
    * 所有需要注入的class
    * */
    private static final ConcurrentHashMap<String, Class<?>> injectClass = new ConcurrentHashMap<>();


    /*
       先扫描到所有的bean,注入到此容器中
    * bean 容器
    * */
    private static final ConcurrentHashMap<String, ClBean> container = new ConcurrentHashMap<>();


    private static final  ConcurrentHashMap<String, Object> postProcessor = new ConcurrentHashMap<>();


    private static final  ConcurrentHashMap<String, ClController> clController = new ConcurrentHashMap<>();

    /*
    * 已经注入过的bean的对象
    * */
    private static final ConcurrentHashMap<String, Object> afterInjectBean = new ConcurrentHashMap<>();

    public static void putBean(String beanName, ClBean clBean){
        container.put(beanName, clBean);
    }


    public static void putClController(String url, ClController controller){
        clController.put(url, controller);
    }

    public static ClController getClController(String url){
        ClController clController = MyContainer.clController.get(url);
        return clController;
    }

    /*
    * Class<T> tClass 代表任意类的Class类型,所以返回这个类型的对象就像
    * 例如 , Cat.class , 返回Cat的对象即可
    * */
    public static <T> ClBean getBean(String beanName, Class<T> tClass){
        if (beanName.equals("")){
            throw new RuntimeException("beanName不能为空");
        }
        Object o = container.get(beanName.toUpperCase());
        if (o != null){
            ClBean clBean = (ClBean) o;
//            两者是同一个Class类
            if (tClass.equals(clBean.getObject().getClass())) {
                return clBean;
            }
        }else{
            // 容其中获取的bean为空,去创建bean
            ClBean clBean = ScannerClass.preCreateBean(beanName, tClass);
            if (clBean != null) {
                //创建完,放入容器,返回bean
                putBean(clBean.getBeanName(), clBean);
                return clBean;
            }
        }
        return null;
    }


    public static void putInjectClass(String injectClassName,Class<?> clazz){
        injectClass.put(injectClassName,clazz);
    }

    public static Class getInjectClass(String injectClassName){
        return injectClass.get(injectClassName);
    }


    public static ConcurrentHashMap<String, Class<?>> getInjectClassMap(){
        return injectClass;
    }

    public static ConcurrentHashMap<String, ClBean> getContainer(){
        return container;
    }

    public static ConcurrentHashMap<String, ClController> getControllerContainer(){
        return clController;
    }

    public static void putPostProcessor(String processorName,Object obj){
        postProcessor.put(processorName,obj);
    }

    public static ConcurrentHashMap<String, Object> getPostProcessor(){
        return postProcessor;
    }


    public static ConcurrentHashMap<String, Object> getAfterInjectBean(){
        return afterInjectBean;
    }

    public static void  putAfterInjectBean(String name,Object object){
        afterInjectBean.put(name, object);
    }



    public static ClBean getBeanWithContainer(String beanName, Class<?> clazs) {
        ClBean clBean = getBean(beanName, clazs);
        if (clBean != null) {
            return clBean;
        }
        return null;
    }





    /*
    * servlet 初始化 注入所有的bean
    * */
    public static void injectServletBean(Class<?> clasz,Object object){
        Field[] declaredFields = clasz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            ClComponent annotation = declaredField.getAnnotation(ClComponent.class);
            if (annotation != null && annotation.isBean() && !annotation.value().equals("")){
                declaredField.setAccessible(true);
                try {
                    ClBean bean = MyContainer.getBeanWithContainer(annotation.value(), declaredField.getType());
                    declaredField.set(object,bean.getObject());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
